<%--    
创建时间：2018年5月15日下午6:03:03   
创 建 人：JobsZhang  
相关说明：   
JDK1.6.0_21 tomcat6.0.29 servlet2.5    
--%>
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webuploaderDemo</title>
<link rel="stylesheet" href="staticresource/layui/css/layui.css">
<link rel="stylesheet" href="staticresource/webuploader/upload.media.css">
<link rel="stylesheet" href="staticresource/css/style.css">
<script src="staticresource/js/jquery-3.2.1.min.js"></script>
<script src="staticresource/layui/layui.all.js"></script>
<script src="staticresource/webuploader/webuploader.js"></script>
<style type="text/css">


.upload-table{
    padding: 2px 12px;
}

.fileQueue{
	height: 300px;
    overflow-x: hidden;
    overflow-y: auto;
    background-color: #f8f8f8;
    width: 100%;
}
.hiden{
	display: none
}
</style>

<script type="text/javascript">
var base = "${pageContext.request.contextPath}";
var element;
var layer;
var index=0;
var batchWebUpload;
var fileAllNum=0;
var fileAllSize=0;
var successNum=0;
var successSize=0;
var  percentages = {}; // 所有文件的进度信息，key为file id
$(function(){
	layui.use(['layer','element','code'], function(){
		  element = layui.element;
		  layer = layui.layer;
		  layui.code({
			  elem: 'pre', //默认值为.layui-code
			  encode: true, //是否转义html标签。默认不开启
			  about: false
		});
		  layer.ready(function(){
			  showWindow()
		  });
	});

	var fileCheckUrl=base+"/file/checkFile";//检测文件是否存在url
	var checkChunkUrl=base+"/file/checkChunk";//检测分片url
	var mergeChunksUrl=base+"/file/mergeChunks";//合并文件请求地址
	
	//监控文件上传的三个时间点(注意：该段代码必须放在WebUploader.create之前)
    //时间点1：:所有分块进行上传之前（1.可以计算文件的唯一标记;2.可以判断是否秒传）   
    //时间点2： 如果分块上传，每个分块上传之前（1.询问后台该分块是否已经保存成功，用于断点续传）
    //时间点3：所有分块上传成功之后（1.通知后台进行分块文件的合并工作）
    WebUploader.Uploader.register({
        "before-send-file":"beforeSendFile",
        "before-send":"beforeSend",
        "after-send-file":"afterSendFile"
    },{
        //时间点1：:所有分块进行上传之前调用此函数
    	//时间点1：:所有分块进行上传之前调用此函数
        beforeSendFile:function(file){//利用md5File（）方法计算文件的唯一标记符
        			 //创建一个deffered
            var deferred = WebUploader.Deferred();
            //1.计算文件的唯一标记，用于断点续传和秒传,获取文件前2m的md5值，越小越快，防止碰撞，把文件名文件大小和md5拼接作为文件唯一标识
            (new WebUploader.Uploader()).md5File(file,0,2*1024*1024).progress(function(percentage){
            	
            	
            }).then(function(val){
                    fileMd5 = file.size+"-"+val+"-"+file.name;//防止碰撞，把文件名文件大小和md5拼接作为文件唯一标识
                    file.fileMd5=fileMd5;
                    //2.请求后台是否保存过该文件，如果存在，则跳过该文件，实现秒传功能
                    $.ajax({
                        type:"POST",
                        url:fileCheckUrl,
                        data:{
                            fileMd5:fileMd5//文件唯一标记
                        },
                        dataType:"json",
                        success:function(response){
                        	console.log(response);
                            if(response.success){
                            	console.log($("#"+file.id).find('.percent').html());
                            	$("#"+file.id).find('.percent').html("100%");
                            	$("#"+file.id).find(".layui-progress-bar").removeClass('layui-bg-blue');
                            	element.progress('progress_'+file.id, '100%');
                            	batchWebUpload.skipFile(file);
                            	successNum++;
                            	successSize+=file.size;
                                //如果存在，则跳过该文件，秒传成功
                                deferred.reject();
                                
                            }else{
                                //继续上传
                                deferred.resolve();
                                
                            }
                        }
                        }
                    );

                });
            //返回deffered
            return deferred.promise();
        },
      //时间点2：如果有分块上传，则 每个分块上传之前调用此函数
        //block:代表当前分块对象
       beforeSend:function(block){//向后台发送当前文件的唯一标记，用于后台创建保存分块文件的目录
    	 //1.请求后台是否保存过当前分块，如果存在，则跳过该分块文件，实现断点续传功能
           var deferred = WebUploader.Deferred();
           //请求后台是否保存完成该文件信息，如果保存过，则跳过，如果没有，则发送该分块内容
           $.ajax({
               type:"POST",
               url:checkChunkUrl,
               data:{
                   //文件唯一标记,敲黑板划重点了，不要用file.fileMd5，不然服务器上的文件会出错
                   fileMd5: block.file.fileMd5,
                   //当前分块下标
                   chunk:block.chunk,
                   //当前分块大小
                   chunkSize:block.end-block.start
               },
               dataType:"json",
               success:function(response){
                   if(response.success){
                	   //分块存在，跳过该分块
                       deferred.reject();
                    
                   }else{
                	   //分块不存在或者不完整，重新发送该分块内容
                       deferred.resolve();
                   }
               }
               }
           );
           //携带当前文件的唯一标记到后台，用于让后台创建保存该文件分块的目录
          // this.owner.options.formData.fileMd5 = block.file.fileMd5;
           return deferred.promise(); 
       },
       //时间点3：所有分块上传成功之后调用此函数
       afterSendFile:function(file){//前台通知后台合并文件
    	   //1.如果分块上传，则通过后台合并所有分块文件
         	 //请求后台合并文件
             $.ajax({
                 type:"POST",
                 url:mergeChunksUrl,
                 data:{
                     //文件唯一标记
                     fileMd5:file.fileMd5,
                     //文件名称
                     fileName:file.name
                 },
                 dataType:"json",
                 success:function(response){
              	   console.log("合并分片完成");
              		console.log(response);
              		$("#"+file.id).find(".layui-progress-bar").removeClass('layui-bg-blue');
                	element.progress('progress_'+file.id, '100%');
                	$("#"+file.id).find('.percent').html("100%");
                	successNum++;
                	successSize+=file.size;
                 }
             });
       }
    });	
	
var batchWebUpload_btn = $("#batchWebUpload");

batchWebUpload = WebUploader.create({ 
	auto:false,
    pick: {
        id: batchWebUpload_btn,//指定选择文件的按钮容器，不指定则不创建按钮。注意 这里虽然写的是 id, 不仅支持 id, 还支持 class, 或者 dom 节点。
        //label : title, 官方建议采用 innerHTML 代替
        //innerHTML : title,
        multiple :true //开启文件多选
    },
    flash:base+'/staticresource/webuploader/Uploader.swf',//ie9一下会自动使用flash上传
   /** accept:{//不验证文件类型了
    	title: '不验证了',//字符串类型，文字描述
        extensions: '*',//允许的文件后缀，不带点，多个用逗号分割。
        mimeTypes: 'application/*,'//多个用逗号分割,怎么不知道咋写的，参考w3c  MIME 参考手册,传送门 http://www.w3school.com.cn/media/media_mimeref.asp
    },**/
    server: base+"/file/uploadChunks",
    //压缩图片，如果图片尺寸超过设置的尺寸，会自动压缩图片，必要时会裁剪
    compress:{
		width: 600,
		height: 600,
		
		// 图片质量，只有type为`image/jpeg`的时候才有效。
		quality: 90,
		
		// 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.
		allowMagnify: false,
		
		// 是否允许裁剪
		crop: false,
		
		// 是否保留头部meta信息。
		preserveHeaders: true,
		
		// 如果发现压缩后文件大小比原来还大，则使用原来图片
		// 此属性可能会影响图片自动纠正功能
		noCompressIfLarger: false
    },
	// 单位字节，如果图片大小小于此值，不会采用压缩。512k  512*1024，如果设置为0，原图尺寸大于设置的尺寸就会压缩；如果大于0，只有在原图尺寸大于设置的尺寸，并且图片大小大于此值，才会压缩
	compressSize: 0,
	fileNumLimit : 10,//验证文件总数量, 超出则不允许加入队列,默认值：undefined,如果不配置，则不限制数量
	fileSizeLimit : 100*1024*1024*1024, //1kb=1024*1024,验证文件总大小是否超出限制, 超出则不允许加入队列。
	fileSingleSizeLimit :10*1024*1024*1024, //验证单个文件大小是否超出限制, 超出则不允许加入队列。
	chunked:true,//是否开启分片上传
	threads:3,
	chunkSize:5*1024*1024,//如果要分片，每一片的文件大小
    prepareNextFile:false//在上传当前文件时，准备好下一个文件,请设置成false，不然开启文件多选你浏览器会卡死
});
//当文件上传成功时触发。file {File} File对象, response {Object}服务端返回的数据
batchWebUpload.on('uploadSuccess',function(file,response){
	layer.msg("上传完成，服务端返回信息请按F12,看控制台：");
	console.log(file);
	if(response.success){
		console.log(response);
	}
})
//错误类型。文件验证不通过时触发
//错误类型说明：Q_EXCEED_NUM_LIMIT 上传文件超过限制的数量
//Q_EXCEED_SIZE_LIMIT文件总大小超出限制
//Q_TYPE_DENIED 当文件类型不对
batchWebUpload.on("error",function(type,file){
	console.log(type);
	if (type=="Q_TYPE_DENIED"){
	    layer.msg("只能上传gif,jpg,jpeg,bmp,png格式文件");
    }else if(type=="Q_EXCEED_SIZE_LIMIT"){
    	layer.msg("所有的文件大小总和不能超过10M");
    }else if(type=='F_EXCEED_SIZE'){
    	layer.msg("单个文件大小不能超过1M");
    }else if(type=='Q_EXCEED_NUM_LIMIT'){
    	layer.msg(typeName+"最多只能上传10个");
    }else if(type=='F_DUPLICATE'){
    	layer.msg(file.name+"已经在上传队列，请勿重复上传");
    }else{
    	layer.msg("上传出错");
    }
}) 


//文件加入队列
batchWebUpload.on("fileQueued",function(file){
	fileAllNum++;
	fileAllSize+=file.size;
	
	
	var fileSize = (file.size/1024/1024.0).toFixed(2)+"M";
	var progress = '<div class="layui-progress " lay-filter="progress_'+file.id
		+'" lay-showPercent="yes" ><div class="layui-progress-bar layui-bg-blue" lay-percent="0"></div></div>';
	var buttons = '<a id="pause_Btn_'+file.id+'" class="layui-btn layui-btn-xs  layui-btn-primary">暂停</a>';
	buttons+='<a id="continue_Btn_'+file.id+'" class="layui-btn layui-btn-xs  layui-btn-primary hiden">继续上传</a>';
	buttons+='<a id="delete_Btn_'+file.id+'" class="layui-btn layui-btn-xs  layui-btn-primary">删除</a>';
	var htm = '<tr id="'+file.id+
	'"><td>'+file.name+
	'</td> <td>'+file.ext+ 
	'</td><td>'+fileSize+
	'</td><td>'+progress+  '</td><td class="percent">0%</td><td class="status">等待上传</td><td>'+buttons+'</td></tr>';
	$("#fileList").append(htm);
	//绑定事件
	$("#pause_Btn_"+file.id).bind('click',function(){
		batchWebUpload.stop(file);
	})
	
	$("#continue_Btn_"+file.id).bind('click',function(){
		batchWebUpload.upload(file);
	})
	
	$("#delete_Btn_"+file.id).bind('click',function(){
		batchWebUpload.removeFile( file, true );//从文件队列移除
	})
	
	percentages[ file.id ] = [ file.size, 0 ];
	file.on('statuschange', function( cur, prev ) {
		
		// 成功
		if ( cur === 'error' || cur === 'invalid' ) {
			percentages[ file.id ][ 1 ] = 1;
		}  else if ( cur === 'queued' ) {
			percentages[ file.id ][ 1 ] = 0;
		} 
	})
	$("#"+file.id).find('.percent').html("0%");
	
	element.progress('progress_'+file.id, '0%');
});

/**从文件队列移除**/
batchWebUpload.on('fileDequeued', function( file ) {
	fileAllNum--;
	fileAllSize-=file.size;
	delete percentages[ file.id ];
});
/**上传之前**/
batchWebUpload.on('uploadBeforeSend', function( block, data, headers ) {
	data.fileMd5 = block.file.fileMd5;
	//block.file.chunks = block.chunks;//当前文件总分片数量
	data.chunks = block.file.chunks;
});


/**上传过程中触发，携带上传进度**/
batchWebUpload.on('uploadProgress',function(file ,percentage){
	var percent=(percentage*100 ).toFixed(2)+"%";
	element.progress('progress_'+file.id, percent);//设置进度条百分比
	
	if(JSON.stringify(percentages) != "{}"){
	    percentages[ file.id ][ 1 ] = percentage;
	}
	if(percentage==1){
		percentages[ file.id ][ 1 ] = 1;
	}
	$("#"+file.id).find(".status").text("正在上传");
	$("#"+file.id).find('.percent').html(percent);
})
 batchWebUpload.on( 'all', function( type ,file) {
	 updateTotalProgress();
	 
	 switch( type ) {
	 case 'uploadComplete':
			parentId = file.id;
			percentages[ file.id ][ 1 ] = 1;
         break;
     case 'uploadFinished':
         break;

     case 'uploadProgress':
         break;
     case 'uploadStart':
         break;

     case 'stopUpload':
         break;

 }
 })
})

/**左下角弹出框**/
function showWindow(){
	if(index!=0){
		try{
			layer.restore(index);
		}catch(err){
			//console.log("弹出层已经打开");
			return index;
		}
		return index;
		
	}
	
	//iframe窗
	index=layer.open({
	  type: 1,
	  title:  ['上传队列', 'font-size:14px;'],
	  closeBtn: 0, //不显示关闭按钮
	  shade: false,
	  area: ['700px', '400px'],
	  offset: 'rb', //右下角弹出
	  anim: 2,
	  maxmin :true,
	  content: $("#fileListDom"), //iframe的url，no代表不显示滚动条
	});
	return index;
}


function startAll(file){
	batchWebUpload.upload(file);
}

function stopUpload(file){
	if(file==undefined){
		batchWebUpload.stop();
	}else{
		batchWebUpload.stop(file);
	}
}

function cancelFile(file){
	batchWebUpload.cancelFile(file);
}


/**设置总百分比**/
function updateTotalProgress() {
	
	
	var fize = (fileAllSize/1024/1024.0).toFixed(2);
	var sSize = (successSize/1024/1024.0).toFixed(2);
	
	$("#fileQueueNum").text(fileAllNum)
	$("#fileQueueSize").text(fize);
    var loaded = 0;
    var total = 0;
   
    var percent = 0;;

    $.each( percentages, function( k, v ) {
        total += v[ 0 ];
        loaded += v[ 0 ] * v[ 1 ];
    } );
    percent = total ? loaded / total : 0;
    $("#successNum").text(successNum);
    $("#successSize").text(sSize);
    var show_pe= Math.round( percent * 100 ) + '%';
    element.progress('sumProgress', show_pe);
    $("#sumPercent").text(show_pe);
}
</script>
</head>
<body>

<a class="layui-btn layui-btn-danger layui-btn-sm" id="batchWebUpload">
  <i class="layui-icon">&#xe857;</i>划重点，多选，分片批量上传+断点续传
</a>

</body>

<div id="fileListDom" class="upload-table" style="display: none">
<a class="layui-btn layui-btn-danger layui-btn-sm" id="startAll" onclick="startAll()">
全部开始
</a>
<a class="layui-btn layui-btn-danger layui-btn-sm" id="stopAll" onclick="stopUpload()">
全部暂停
</a>
<table class="layui-table" lay-size="sm">
 <colgroup>
    <col width="200">
    <col width="150">
    <col width="150">
    <col width="350">
    <col width="150">
    <col width="200">
    <col width="450">
    <col>
  </colgroup>
  <thead>
    <tr>
      <th>文件名</th>
      <th>文件类型</th>
      <th>文件大小</th>
      <th>进度</th>
      <th>百分比</th>
      <th>状态</th>
      <th>操作</th>
    </tr> 
 </thead>
  <tbody id="fileList" class="fileQueue">
  
  </tbody>
  <tfoot id="fileInfo">
  	<tr>
  		<td colspan="4">
  			<span>选中<span id="fileQueueNum">0</span>个文件，共<span id="fileQueueSize">0</span>M。</span><br>
  			<span>上传成功<span id="successNum">0</span>个文件，共<span id="successSize">0</span>M。</span>
  		</td>
  		<td >
  			<span id="sumPercent"></span>
  			
  		</td>
  		<td colspan="2">
	  		<div class="layui-progress" lay-showPercent="yes" lay-filter="sumProgress">
			  <div class="layui-progress-bar" lay-percent="0%" id="sumProgress_bar" ></div>
			</div>
  		</td>
  	</tr>
  </tfoot>
</table>

</div>
</html>